package com.ccl.iot.device;

import android.graphics.Bitmap;

import com.ccl.iot.IOTDataType;
import com.ccl.iot.IOTNetAPIEnum.EIOT_NETWORK_TYPE;
import com.ccl.iot.IOTObject;
import com.ccl.iot.R;
import com.ccl.iot.device.IOTProbe.OnRegDataChangedListener;
import com.ccl.iot.dvr.utils.Consts;
import com.ccl.iot.dvr.utils.HDImageManager;
import com.ccl.iot.object.IOTDeviceInfoEx;
import com.ccl.iot.privates.DimmerTurnSpeedDialog.DimmerTurnSpeed;
import com.ccl.iot.privates.QueueInvokeBuffer;
import com.ccl.iot.privates.QueueInvokeBuffer.InvokeDelegate;

public class IOTRgbLight extends IOTDeviceWithState implements DimmerTurnSpeed, SwitchDevice, IOTObject.IOTDVRInner {

    /**
     * 寄存器数据
     */
    private byte[] mRegData = new byte[20];
    // 打开延时, 最小值1秒
    private short mOnDelay = 1;
    // 关闭延时, 最小值1秒
    private short mOffDelay = 1;
    // 每种颜色的最大值
//	private short mMaxLevel = 0;
    // 通过开关打开灯时的颜色值
    private long mOnState = 0;
    // 设备当前的颜色值
    private long mCurrentState = 0;

    // 存储当前颜色的寄存器地址
    private final static int STATEADDRESS = 12;

    // 当设备不是和用户在同一个局域网时不能连续写入寄存器
    private QueueInvokeBuffer<long[]> mRemoteBuffer;

    private long mStartTime = 0;

    public IOTRgbLight(long aDevID, IOTDeviceInfoEx aDeviceInfo, int aStateAddress, int aStateSize) {
        super(aDevID, aDeviceInfo, aStateAddress, aStateSize);
    }

    @Override
    public void updateRegister(int aAddress, int aSize, byte[] aData, int aDataPos, int aNetWork, long time) {
        saveRegister(aAddress, aSize, aData, aNetWork);
        int regAddress = getRegisterAddress();
        synchronized (mRegData) {
            // 更新寄存器信息
            if (aAddress == 0 && aSize > regAddress) {
                int size = aSize - regAddress;
                for (int i = 0; i < size; i++) {
                    mRegData[i] = aData[regAddress + i];
                }
            } else if (aAddress >= regAddress && aSize > 0 && aSize < mRegData.length) {
                for (int i = 0; i < aSize; i++) {
                    mRegData[aAddress - regAddress + i] = aData[i];
                }
            }
        }

        // 获取开关延时
        mOnDelay = mRegData[0];
        mOffDelay = mRegData[1];

        // 0x000 ~ 0xFFF
//		mMaxLevel = IOTDataType.C16(mRegData, 2);

        // RGBW
        mOnState = IOTDataType.C64(mRegData, 4);
        mCurrentState = IOTDataType.C64(mRegData, STATEADDRESS);

        // 更新显示快和拖动条
        if (mListener != null) {
            mListener.onRegDataChange();
        }

        // 寄存器数据改变的回调
        afterStateChange();
    }

    @Override
    public String[] getStateIDs() {
        return null;
    }

    /**
     * 设备开关信息
     *
     * @return 设备开关
     */
    @Override
    public boolean isOn() {
        return mCurrentState != 0;
    }

    /**
     * 设备的开关
     *
     * @param b 开:关
     */
    @Override
    public void turn(boolean b) {
        long state = b ? mOnState : 0;
        byte[] data = IOTDataType.C8Array(state);
        iRegisterInterface.writeRegister(this, getRegisterAddress() + STATEADDRESS, data.length, data, EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_BOTH);
    }

    /**
     * 修改设备颜色
     *
     * @param color     要修改的颜色
     * @param address   寄存器地址, 值为0则从RGBW中的R开始, 否则从W开始
     * @param netState  设备网络信息(是否为本地设备)
     * @param isTouchUp 是否抬起手指, 要保证设备显示的颜色一定为手机抬起时的颜色
     */
    public void disColoring(long color, int address, int netState, boolean isTouchUp) {
        final byte[] regData = IOTDataType.C8Array(color);

        // 获取颜色时将RGB和W分开了, 所以写RGB和写W颜色时的数据长度和地址都不一样, 通过地址来决定数据长度
        int length = regData.length;
        if (address != 0) {
            length = 2;
        }
        if (getNetWorkState() == EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_LOCAL) {
            // 本地设备的寄存器写入方式
            long startTime = System.currentTimeMillis();

			/*
             * 通过本地网寄存器写入数据时, 如果距离上一次操作寄存器的时间超过了10秒,设备会验证用户的请求.
			 * 这是要通过服务器写入数据, 否则就算写入多次也可能没有真正写入寄存器. 
			 * 如果没有超过十秒就没必要通过服务器了
			 */
            if (startTime - mStartTime >= 10000) {
                // 通过服务器, 针对设备的验证请求
                iRegisterInterface.writeRegister(this, getRegisterAddress() + STATEADDRESS + address, length, regData, EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_BOTH);
            } else {
                // 通过本地写寄存器
                iRegisterInterface.writeRegister(this, getRegisterAddress() + STATEADDRESS + address, length, regData, EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_LOCAL);
                if (isTouchUp) {
                    // 当手指抬起, 将抬起时取得的颜色通过队列任务处理器处理, 以确保真正写入了寄存器
                    remoteSetColor(color, address, EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_BOTH, length);
                }
            }
            mStartTime = System.currentTimeMillis();
        } else {

            long startTime = System.currentTimeMillis();

            // 当设备不在本地, 读写寄存器会有延时, 而且不能频繁操作
            if (startTime - mStartTime > 300 || isTouchUp) {
                mStartTime = System.currentTimeMillis();
                remoteSetColor(color, address, netState, length);
            }
        }

    }

    /**
     * 通过队列来处理任务, 并且最后一条数据一定会写入寄存器
     *
     * @param RegColor    要写入寄存器的颜色数据
     * @param RegAddress  寄存器地址
     * @param RegNetState 网络状态
     * @param RegLength   数据长度,单位:byte
     */
    private void remoteSetColor(long RegColor, int RegAddress, int RegNetState, int RegLength) {

        if (mRemoteBuffer == null) {
            mRemoteBuffer = new QueueInvokeBuffer<long[]>("Remote RGBBulb buffer", 200, new InvokeDelegate<long[]>() {
                private int count = 0;

                @Override
                public void onInvoke(long[] colorData) {
                    byte[] data = IOTDataType.C8Array(colorData[0]);

                    iRegisterInterface.writeRegister(IOTRgbLight.this, getRegisterAddress() + STATEADDRESS + (int) colorData[1], (int) colorData[2], data, EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_BOTH);
                }

                @Override
                public void lastTask(long[] colorData) {
                    // 当当前设备的颜色和最后一个写入寄存器的颜色不一致就继续写入寄存器, 如果写了10次后还不成功就取消了
                    if ((colorData[2] != 2 ? mCurrentState != colorData[0] : mCurrentState >> 48 != colorData[0]) && count <= 10) {
                        mRemoteBuffer.put(colorData);
                        count++;
                    } else {
                        count = 0;
                    }
                }

            });
        }

        mRemoteBuffer.put(new long[]{RegColor, RegAddress, RegLength});
    }

    /**
     * 获取当前状态值
     *
     * @return
     */
    public long getCurrentState() {
        return mCurrentState;
    }

    /**
     * 寄存器变化的回调接口
     */
    private OnRegDataChangedListener mListener = null;

    public void setRegDataChangeListener(OnRegDataChangedListener l) {
        mListener = l;
    }

    @Override
    public String getDeviceName() {
        return getName();
    }

    @Override
    public short getTurnSpeed() {
        return (short) (mOnDelay | (mOffDelay << 8));
    }

    @Override
    public short getTurnDimmer() {
        return 0;
    }

    @Override
    public void setTurnSpeed(byte[] speed) {
        iRegisterInterface.writeRegister(this, getRegisterAddress(), speed.length, speed, EIOT_NETWORK_TYPE.EIOT_NETWORK_TYPE_BOTH);
    }

    @Override
    public void setDimmer(int state, boolean isStop) {

    }

    @Override
    public void onStartDimmer() {

    }

    @Override
    public byte[] getRegister() {
        return mRegData;
    }

    @Override
    public int getImageId() {
        int id = getSplitIconId();
        if (id >= DeviceIconProvider.ICON_LIST_SWITCH_ON.length){
            id = 0;
        }
        return isOn() ? DeviceIconProvider.ICON_LIST_SWITCH_ON[id] : DeviceIconProvider.ICON_LIST_SWITCH_OFF[id];
    }

    @Override
    public boolean setImage(Bitmap bitmap) {

//        String tID = getImageID(Consts.RGB_LIGHT);
//
//        getImageCount();
//
//        if (bitmap == null) {
//            if (ImageManager.RemoveBitmap(tID)) {
//                return true;
//            }
//        } else {
//            ImageManager.SetBitmap(tID, bitmap);
//            return true;
//        }
//
//        return false;


        String imageID = getImageID(Consts.RGB_LIGHT);
        if (bitmap != null){
            return HDImageManager.getInstince().setBitmap(imageID,bitmap);
        }

        return false;
    }

    @Override
    public Bitmap getImage() {

//        String tID = getImageID(Consts.RGB_LIGHT);
//        Bitmap tBitmap = ImageManager.GetBitmap(tID);
//        return tBitmap;

        String imageID = getImageID(Consts.RGB_LIGHT);
        return HDImageManager.getInstince().getBitmap(imageID);

    }

    public String getImagePath(){
        String imageID = getImageID(Consts.RGB_LIGHT);
        return HDImageManager.getInstince().getBitmapPath(imageID);
    }

    @Override
    public int getImageCount() {

//        if (ImageManager.ContainsBitmap(getImageID(Consts.RGB_LIGHT))) {
//            return 1;
//        }
//        return 0;

        if (HDImageManager.getInstince().containsBitmap(getImageID(Consts.RGB_LIGHT))){
            return 1;
        }
        return 0;
    }

    @Override
    public void onViewClick() {
        turn(!isOn());
    }

    @Override
    public int getCornerId() {
        return R.drawable.icon_colorful;
    }
}
